﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace ExpressionBuilder.CustomExtend
{
    public static class TableTypeExtend
    {

        /// <summary>
        /// 获取表名和类型的关系
        /// </summary>
        public static Dictionary<string, TableClassInfo> _entityTypes = new();

        /// <summary>
        /// 备注的默认值
        /// </summary>
        private const string defaultSummary = "No summary";

        /// <summary>
        /// 获取类的属性信息
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        public static TableClassInfo GetTableClassInfo<TSource>(this TSource source)
        {
            return GetTableClassInfo<TSource>();
        }



        /// <summary>
        /// 获取类的属性信息
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <returns></returns>
        public static TableClassInfo GetTableClassInfo<TSource>()
        {
            TableClassInfo result = new();
            var type = typeof(TSource);
            if (type == null) return result;
            var tableName = type.GetTableName();
            result.ClassType = type;
            result.TableName = tableName;
            if (!string.IsNullOrEmpty(tableName) && _entityTypes.ContainsKey(tableName))
                return _entityTypes[tableName];
            Assembly? assembly = Assembly.GetAssembly(type);  // 获取包含 T 的程序集
            if (assembly == null) return result;
            string assemblyPath = assembly.Location;   // 获取程序集的文件路径
            string xmlFilePath = Path.ChangeExtension(assemblyPath, ".xml");   // 构建 XML 注释文件的路径
            XDocument xdoc = XDocument.Load(xmlFilePath);
            string typeName = $"T:{type.FullName}";
            result.ClassSummary = xdoc.GetSummaryStr(typeName);
            PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            foreach (var property in properties)
            {
                if (property is null) continue;
                string memberName = $"P:{property?.DeclaringType?.FullName}.{property?.Name}";
                string propertySummary = xdoc.GetSummaryStr(memberName);
                result.TablePropertyInfos.Add(new TablePropertyInfo
                {
                    PropertyName = property.Name,
                    PropertySummary = propertySummary,
                    PropertyType = property.PropertyType,
                    PropertyTypeName = property.PropertyType.Name,
                });
            }
            _entityTypes[tableName] = result;
            return result;
        }


        /// <summary>
        /// 获取table是否是数据库表名
        /// </summary>
        private static string GetTableName(this Type type)
        {
            var tableName = string.Empty;
            if (type.IsClass && type.GetCustomAttribute<TableAttribute>() != null)
            {
                var tableAttribute = type.GetCustomAttribute<TableAttribute>();
                tableName = tableAttribute?.Name;
            }
            return tableName;
        }

        /// <summary>
        /// 获取路径的xml备注的属性文件，
        /// 确保在被加载程序集的属性（csproj）文件中启用了 XML 注释生成
        /// <PropertyGroup>
        /// <GenerateDocumentationFile>true</GenerateDocumentationFile>
        /// </PropertyGroup>
        /// </summary>
        /// <param name="xmlFilePath"></param>
        /// <param name="property"></param>
        /// <returns></returns>
        public static string GetPropertySummary(string xmlFilePath, PropertyInfo property)
        {
            if (File.Exists(xmlFilePath))
            {
                string memberName = $"P:{property?.DeclaringType?.FullName}.{property?.Name}";
                XDocument xdoc = XDocument.Load(xmlFilePath);
                return xdoc.GetSummaryStr(memberName);
            }
            return defaultSummary;
        }


        /// <summary>
        /// 获取类的备注
        /// </summary>
        /// <param name="xmlFilePath"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static string GetClassSummary(string xmlFilePath, Type type)
        {

            if (File.Exists(xmlFilePath))
            {
                XElement xmlDocumentation = XElement.Load(xmlFilePath);
                string typeName = $"T:{type.FullName}";
                XDocument xdoc = XDocument.Load(xmlFilePath);
                return xdoc.GetSummaryStr(typeName);
            }
            return defaultSummary;
        }

        /// <summary>
        /// 获取节点备注
        /// </summary>
        /// <param name="xdoc"></param>
        /// <param name="memberName">节点名称</param>
        /// <returns></returns>
        private static string GetSummaryStr(this XDocument xdoc, string memberName)
        {
            var typeElement = xdoc?.Element("doc")?.Element("members")?.Elements("member").FirstOrDefault(e => e?.Attribute("name")?.Value == memberName);
            if (typeElement != null)
            {
                XElement? summaryElement = typeElement.Element("summary");
                return summaryElement?.Value.Trim() ?? defaultSummary;
            }
            return defaultSummary;
        }

    }
}
